---
title: InfoController
summary: Tracking status polling and stateless PDF inspection/validation operations.
status: draft
owner: Not determined from source
last_reviewed: 2026-09-17
library: PdfAPI
reference_type: embedded
---

# InfoController

`InfoController` exposes tracking-status polling for previously tracked requests and six stateless PDF inspection/validation operations that perform no persistence. None of its seven actions carry a `try`/`catch`; validation failures escape to the framework.

| Field | Value |
| --- | --- |
| **Controller** | `InfoController` |
| **Base** | `System.Web.Http.ApiController` |
| **Route prefix** | `[RoutePrefix("v1/info")]` |
| **Source** | `PdfAPI\Controllers\v1\InfoController.cs` |
| **Controller-level authorization** | None in code |
| **Error handling** | No `try`/`catch` — exceptions escape to the framework (`IncludeErrorDetailPolicy.Always` produces exception detail); response then passes through `ApiResponseHandler`, whose final outer envelope is unknown** ([details](../endpoints.md#error-response-shape)) |
| **Endpoints** | 7 |

---

## GET v1/info/track/{trackingId}

Polls a tracking record's status, optionally sleeping and re-reading while the status is `Scheduled` or `Processing`, up to a caller-specified retry count.

| Field | Value |
| --- | --- |
| **HTTP verb** | `GET` |
| **Resolved route** | `v1/info/track/{trackingId}` |
| **Route composition** | `[RoutePrefix("v1/info")]` + `[Route("track/{trackingId}")]` |
| **Action** | `CheckPdfTrackingStatus(long trackingId, int retryIntervalMilliseconds, int retryCount)` |
| **Return type** | `PdfAPI.Core.PdfTrackingInfo` (returned bare, not wrapped in `IHttpActionResult`) |
| **Authorization** | [None in code](../authentication-authorization.md#authorization-enforcement) |
| **Idempotent** | Yes — reads the tracking record without mutating it* |
| **Operation** | [OP-CHECK-TRACKING-STATUS](../operations/op-check-tracking-status.md) |

### Track status parameters

| Name | In | Type | Required | Default | Binding | Purpose |
| --- | --- | --- | --- | --- | --- | --- |
| `trackingId` | Route | `long` | Yes | — | Route segment | Identifies the tracking record |
| `retryIntervalMilliseconds` | Query | `int` | No | `1000` | `[FromUri]`* | Sleep interval between polling reads |
| `retryCount` | Query | `int` | No | `0` | `[FromUri]`* | Number of additional reads while the status is `Scheduled`/`Processing` ([BR-PDFAPI-014](../business-rules.md#br-pdfapi-014-status-check-polling-loop)) |

### Track status response

| Field | Value |
| --- | --- |
| **DTO** | `PdfAPI.Core.PdfTrackingInfo` |
| **Media type** | `application/json` |

| Property | Type | Nullable | Purpose |
| --- | --- | --- | --- |
| `Status` | `PdfStatus` | No | Current tracked status |
| `FileId` | `string` | Yes | Correlation id for the tracked document |
| `FilePath` | `string` | Yes | Output file path, when set |
| `TrackingId` | value type | No | Echoes the requested tracking id |

### Track status codes

| Status | Condition | Body |
| --- | --- | --- |
| `200 OK` | Read succeeds | `PdfTrackingInfo` |

### Track status errors

| Error status | Trigger | Produced by | Body |
| --- | --- | --- | --- |
| `500 Internal Server Error` | Any repository/database exception escapes to the framework — no `try`/`catch` on this action* | Framework (uncaught exception, `IncludeErrorDetailPolicy.Always`) | Exception detail |

The `Body` column above describes only the pre-envelope detail produced by the framework.
Every response also passes through the globally registered `ApiResponseHandler` message handler (`SAIF.Web.API` package), which wraps or post-processes the HTTP response for the whole service. That handler's exact outer envelope shape is implemented inside the package and is not visible in this repository — see [Endpoints: Error response shape](../endpoints.md#error-response-shape).

### Track status business rules

- [BR-PDFAPI-014](../business-rules.md#br-pdfapi-014-status-check-polling-loop) — the status check polls while the status is `Scheduled` or `Processing`, sleeping `retryIntervalMilliseconds` between reads, up to `retryCount` attempts.

### Authorization (GET v1/info/track/{trackingId})

No authorization attribute or programmatic check is present. See [Authentication and authorization](../authentication-authorization.md).

### Side effects and idempotency (GET v1/info/track/{trackingId})

| Aspect | Finding |
| --- | --- |
| Records written | None — read-only |
| Downstream calls | None identified |
| Files or messages produced | None |
| Repeat-call behavior | Read-only; safe to repeat |

### Example (GET v1/info/track/{trackingId})

```http
GET v1/info/track/12345?retryCount=3&retryIntervalMilliseconds=500 HTTP/1.1
Host: <host>
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "Status": "Succeeded",
  "TrackingId": 12345
}
```

---

## POST v1/info/pages/count

Returns the page count of a submitted PDF, validating that the payload is a real PDF first.

| Field | Value |
| --- | --- |
| **HTTP verb** | `POST` |
| **Resolved route** | `v1/info/pages/count` |
| **Route composition** | `[RoutePrefix("v1/info")]` + `[Route("pages/count")]` |
| **Action** | `GetPageCount(byte[] pdf)` |
| **Return type** | `int` (returned bare) |
| **Authorization** | [None in code](../authentication-authorization.md#authorization-enforcement) |
| **Idempotent** | Yes — read-only inspection |
| **Operation** | [OP-GET-PAGE-COUNT](../operations/op-get-page-count.md) |

### Page count parameters

| Name | In | Type | Required | Default | Binding | Purpose |
| --- | --- | --- | --- | --- | --- | --- |
| `pdf` | Body | `byte[]` | Yes | — | `[FromBody]`* | The PDF bytes to inspect |

### Page count response

| Field | Value |
| --- | --- |
| **DTO** | — (`int`) |
| **Media type** | `application/json` |

### Page count status codes

| Status | Condition | Body |
| --- | --- | --- |
| `200 OK` | Payload is a valid PDF | Page count as a JSON number |

### Page count errors

| Error status | Trigger | Produced by | Body |
| --- | --- | --- | --- |
| `500 Internal Server Error` | `PdfException` thrown by `PdfClientService.ValidatePdf` when the payload is not a PDF ([BR-PDFAPI-005](../business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature)) | Framework (uncaught exception) | Exception detail |

The `Body` column above describes only the pre-envelope detail produced by the framework.
Every response also passes through the globally registered `ApiResponseHandler` message handler (`SAIF.Web.API` package), which wraps or post-processes the HTTP response for the whole service. That handler's exact outer envelope shape is implemented inside the package and is not visible in this repository — see [Endpoints: Error response shape](../endpoints.md#error-response-shape).

### Page count business rules

- [BR-PDFAPI-005](../business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature) — PDF validity is determined by the `%PDF-` file signature; failure raises `PdfException`.

### Authorization (POST v1/info/pages/count)

No authorization attribute or programmatic check is present. See [Authentication and authorization](../authentication-authorization.md).

### Side effects and idempotency (POST v1/info/pages/count)

| Aspect | Finding |
| --- | --- |
| Records written | None |
| Downstream calls | None identified |
| Files or messages produced | None |
| Repeat-call behavior | Read-only; safe to repeat |

### Example (POST v1/info/pages/count)

```http
POST v1/info/pages/count HTTP/1.1
Host: <host>
Content-Type: application/json

"<base64 pdf bytes>"
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

7
```

---

## POST v1/info/fields/exist

Reports whether a submitted PDF contains form fields.

| Field | Value |
| --- | --- |
| **HTTP verb** | `POST` |
| **Resolved route** | `v1/info/fields/exist` |
| **Route composition** | `[RoutePrefix("v1/info")]` + `[Route("fields/exist")]` |
| **Action** | `HasFormFields(byte[] pdf, bool useClient)` |
| **Return type** | `bool` (returned bare) |
| **Authorization** | [None in code](../authentication-authorization.md#authorization-enforcement) |
| **Idempotent** | Yes — read-only inspection |
| **Operation** | [OP-HAS-FORM-FIELDS](../operations/op-has-form-fields.md) |

### Form fields exist parameters

| Name | In | Type | Required | Default | Binding | Purpose |
| --- | --- | --- | --- | --- | --- | --- |
| `pdf` | Body | `byte[]` | Yes | — | `[FromBody]`* | The PDF bytes to inspect |
| `useClient` | Query | `bool` | No | `true` | `[FromUri]`* | Selects the iTextSharp client path (`true`) or the Syncfusion helper path (`false`) ([BR-PDFAPI-021](../business-rules.md#br-pdfapi-021-form-field-inspection-client-selection)) |

### Form fields exist response

| Field | Value |
| --- | --- |
| **DTO** | — (`bool`) |
| **Media type** | `application/json` |

### Form fields exist status codes

| Status | Condition | Body |
| --- | --- | --- |
| `200 OK` | Payload is a valid PDF | `true`/`false` |

### Form fields exist errors

| Error status | Trigger | Produced by | Body |
| --- | --- | --- | --- |
| `500 Internal Server Error` | `PdfException` on a non-PDF payload* | Framework (uncaught exception) | Exception detail |

The `Body` column above describes only the pre-envelope detail produced by the framework.
Every response also passes through the globally registered `ApiResponseHandler` message handler (`SAIF.Web.API` package), which wraps or post-processes the HTTP response for the whole service. That handler's exact outer envelope shape is implemented inside the package and is not visible in this repository — see [Endpoints: Error response shape](../endpoints.md#error-response-shape).

### Form fields exist business rules

- [BR-PDFAPI-021](../business-rules.md#br-pdfapi-021-form-field-inspection-client-selection) — form-field inspection defaults to the iTextSharp client implementation and uses the Syncfusion helper only when the caller explicitly opts out.

### Authorization (POST v1/info/fields/exist)

No authorization attribute or programmatic check is present. See [Authentication and authorization](../authentication-authorization.md).

### Side effects and idempotency (POST v1/info/fields/exist)

| Aspect | Finding |
| --- | --- |
| Records written | None |
| Downstream calls | None identified |
| Files or messages produced | None |
| Repeat-call behavior | Read-only; safe to repeat |

### Example (POST v1/info/fields/exist)

```http
POST v1/info/fields/exist?useClient=true HTTP/1.1
Host: <host>
Content-Type: application/json

"<base64 pdf bytes>"
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

true
```

---

## POST v1/info/fields/flatten

Flattens the form fields in a submitted PDF and returns the flattened document bytes.

| Field | Value |
| --- | --- |
| **HTTP verb** | `POST` |
| **Resolved route** | `v1/info/fields/flatten` |
| **Route composition** | `[RoutePrefix("v1/info")]` + `[Route("fields/flatten")]` |
| **Action** | `FlattenFormFields(byte[] pdf, bool useClient)` |
| **Return type** | `byte[]` (returned bare; serialized as base64 by the JSON formatter*) |
| **Authorization** | [None in code](../authentication-authorization.md#authorization-enforcement) |
| **Idempotent** | Yes — produces the same flattened output for the same input* |
| **Operation** | [OP-FLATTEN-FORM-FIELDS](../operations/op-flatten-form-fields.md) |

### Flatten fields parameters

| Name | In | Type | Required | Default | Binding | Purpose |
| --- | --- | --- | --- | --- | --- | --- |
| `pdf` | Body | `byte[]` | Yes | — | `[FromBody]`* | The PDF bytes to flatten |
| `useClient` | Query | `bool` | No | `true` | `[FromUri]`* | Selects the iTextSharp client path (`true`) or the Syncfusion helper path (`false`) ([BR-PDFAPI-021](../business-rules.md#br-pdfapi-021-form-field-inspection-client-selection)) |

### Flatten fields response

| Field | Value |
| --- | --- |
| **DTO** | — (`byte[]`, flattened PDF bytes) |
| **Media type** | `application/json` (base64-encoded string)* |

### Flatten fields status codes

| Status | Condition | Body |
| --- | --- | --- |
| `200 OK` | Payload is a valid PDF | Flattened PDF bytes (base64) |

### Flatten fields errors

| Error status | Trigger | Produced by | Body |
| --- | --- | --- | --- |
| `500 Internal Server Error` | `PdfException` on a non-PDF payload* | Framework (uncaught exception) | Exception detail |

The `Body` column above describes only the pre-envelope detail produced by the framework.
Every response also passes through the globally registered `ApiResponseHandler` message handler (`SAIF.Web.API` package), which wraps or post-processes the HTTP response for the whole service. That handler's exact outer envelope shape is implemented inside the package and is not visible in this repository — see [Endpoints: Error response shape](../endpoints.md#error-response-shape).

### Flatten fields business rules

- [BR-PDFAPI-021](../business-rules.md#br-pdfapi-021-form-field-inspection-client-selection) — form-field flattening defaults to the iTextSharp client implementation and uses the Syncfusion helper only when the caller explicitly opts out.

### Authorization (POST v1/info/fields/flatten)

No authorization attribute or programmatic check is present. See [Authentication and authorization](../authentication-authorization.md).

### Side effects and idempotency (POST v1/info/fields/flatten)

| Aspect | Finding |
| --- | --- |
| Records written | None |
| Downstream calls | None identified |
| Files or messages produced | None persisted — flattened bytes are returned in the response |
| Repeat-call behavior | Same output for the same input; safe to repeat* |

### Example (POST v1/info/fields/flatten)

```http
POST v1/info/fields/flatten?useClient=true HTTP/1.1
Host: <host>
Content-Type: application/json

"<base64 pdf bytes>"
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

"<base64 flattened pdf bytes>"
```

---

## POST v1/info/validate

Reports whether the submitted bytes are a valid PDF, returning `false` rather than failing for a non-PDF payload.

| Field | Value |
| --- | --- |
| **HTTP verb** | `POST` |
| **Resolved route** | `v1/info/validate` |
| **Route composition** | `[RoutePrefix("v1/info")]` + `[Route("validate")]` |
| **Action** | `IsPdf(byte[] pdf)` |
| **Return type** | `bool` (returned bare) |
| **Authorization** | [None in code](../authentication-authorization.md#authorization-enforcement) |
| **Idempotent** | Yes — read-only inspection |
| **Operation** | [OP-IS-PDF](../operations/op-is-pdf.md) |

### Validate PDF parameters

| Name | In | Type | Required | Default | Binding | Purpose |
| --- | --- | --- | --- | --- | --- | --- |
| `pdf` | Body | `byte[]` | Yes | — | `[FromBody]`* | The bytes to validate |

### Validate PDF response

| Field | Value |
| --- | --- |
| **DTO** | — (`bool`) |
| **Media type** | `application/json` |

### Validate PDF status codes

| Status | Condition | Body |
| --- | --- | --- |
| `200 OK` | Always — returns `false` for a non-PDF payload rather than failing ([BR-PDFAPI-005](../business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature)) | `true`/`false` |

### Validate PDF errors

No error status codes are identified for this endpoint.

### Validate PDF business rules

- [BR-PDFAPI-005](../business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature) — PDF validity is determined by the `%PDF-` file signature.

### Authorization (POST v1/info/validate)

No authorization attribute or programmatic check is present. See [Authentication and authorization](../authentication-authorization.md).

### Side effects and idempotency (POST v1/info/validate)

| Aspect | Finding |
| --- | --- |
| Records written | None |
| Downstream calls | None identified |
| Files or messages produced | None |
| Repeat-call behavior | Read-only; safe to repeat |

### Example (POST v1/info/validate)

```http
POST v1/info/validate HTTP/1.1
Host: <host>
Content-Type: application/json

"<base64 bytes>"
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

true
```

---

## POST v1/info/validate/pdfa

Reports whether the submitted PDF conforms to PDF/A, inspecting XMP metadata for a `pdfaid:conformance` value of `A` or `B`.

| Field | Value |
| --- | --- |
| **HTTP verb** | `POST` |
| **Resolved route** | `v1/info/validate/pdfa` |
| **Route composition** | `[RoutePrefix("v1/info")]` + `[Route("validate/pdfa")]` |
| **Action** | `IsPdfa(byte[] pdf)` |
| **Return type** | `bool` (returned bare) |
| **Authorization** | [None in code](../authentication-authorization.md#authorization-enforcement) |
| **Idempotent** | Yes — read-only inspection |
| **Operation** | [OP-VALIDATE-PDFA](../operations/op-validate-pdfa.md) |

### Validate PDF/A parameters

| Name | In | Type | Required | Default | Binding | Purpose |
| --- | --- | --- | --- | --- | --- | --- |
| `pdf` | Body | `byte[]` | Yes | — | `[FromBody]`* | The PDF bytes to inspect |

### Validate PDF/A response

| Field | Value |
| --- | --- |
| **DTO** | — (`bool`) |
| **Media type** | `application/json` |

### Validate PDF/A status codes

| Status | Condition | Body |
| --- | --- | --- |
| `200 OK` | Always — the Syncfusion implementation catches its own exceptions and returns `false` | `true`/`false` |

### Validate PDF/A errors

No error status codes are identified on this path.

### Validate PDF/A business rules

No business rule beyond the general PDF/A conformance inspection is identified for this endpoint.

### Authorization (POST v1/info/validate/pdfa)

No authorization attribute or programmatic check is present. See [Authentication and authorization](../authentication-authorization.md).

### Side effects and idempotency (POST v1/info/validate/pdfa)

| Aspect | Finding |
| --- | --- |
| Records written | None |
| Downstream calls | None identified |
| Files or messages produced | None |
| Repeat-call behavior | Read-only; safe to repeat |

### Example (POST v1/info/validate/pdfa)

```http
POST v1/info/validate/pdfa HTTP/1.1
Host: <host>
Content-Type: application/json

"<base64 pdf bytes>"
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

false
```

---

## POST v1/info/version

Returns the PDF version header found in the submitted document.

| Field | Value |
| --- | --- |
| **HTTP verb** | `POST` |
| **Resolved route** | `v1/info/version` |
| **Route composition** | `[RoutePrefix("v1/info")]` + `[Route("version")]` |
| **Action** | `Version(byte[] pdf)` |
| **Return type** | `string` (returned bare) |
| **Authorization** | [None in code](../authentication-authorization.md#authorization-enforcement) |
| **Idempotent** | Yes — read-only inspection |
| **Operation** | [OP-GET-PDF-VERSION](../operations/op-get-pdf-version.md) |

### PDF version parameters

| Name | In | Type | Required | Default | Binding | Purpose |
| --- | --- | --- | --- | --- | --- | --- |
| `pdf` | Body | `byte[]` | Yes | — | `[FromBody]`* | The PDF bytes to inspect |

### PDF version response

| Field | Value |
| --- | --- |
| **DTO** | — (`string`, e.g. `"1.7"`, or `""` when no header match) |
| **Media type** | `application/json` |

### PDF version status codes

| Status | Condition | Body |
| --- | --- | --- |
| `200 OK` | Payload is a valid PDF | Version string, or empty string when no header match |

### PDF version errors

| Error status | Trigger | Produced by | Body |
| --- | --- | --- | --- |
| `500 Internal Server Error` | `PdfException` on a non-PDF payload ([BR-PDFAPI-005](../business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature)) | Framework (uncaught exception) | Exception detail |

The `Body` column above describes only the pre-envelope detail produced by the framework.
Every response also passes through the globally registered `ApiResponseHandler` message handler (`SAIF.Web.API` package), which wraps or post-processes the HTTP response for the whole service. That handler's exact outer envelope shape is implemented inside the package and is not visible in this repository — see [Endpoints: Error response shape](../endpoints.md#error-response-shape).

### PDF version business rules

- [BR-PDFAPI-005](../business-rules.md#br-pdfapi-005-pdf-validity-by-file-signature) — PDF validity is determined by the `%PDF-` file signature; failure raises `PdfException`.

### Authorization (POST v1/info/version)

No authorization attribute or programmatic check is present. See [Authentication and authorization](../authentication-authorization.md).

### Side effects and idempotency (POST v1/info/version)

| Aspect | Finding |
| --- | --- |
| Records written | None |
| Downstream calls | None identified |
| Files or messages produced | None |
| Repeat-call behavior | Read-only; safe to repeat |

### Example (POST v1/info/version)

```http
POST v1/info/version HTTP/1.1
Host: <host>
Content-Type: application/json

"<base64 pdf bytes>"
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

"1.7"
```

---

## Related documentation
- [API index](../index.md)
- [Overview](../overview.md)
- [Architecture](../architecture.md)
- [Endpoints](../endpoints.md)
- [Authentication and authorization](../authentication-authorization.md)
- [Dependencies](../dependencies.md)
- [Configuration](../configuration.md)
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Data model](../data-model.md)
- [Operational runbook](../operational-runbook.md)
- [Tech debt](../tech-debt.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts. Statements
> marked with `**` could not be confirmed; treat as unknown until verified.

## Sources
- PdfAPI\Controllers\v1\InfoController.cs
- PdfAPI\Services\PdfTrackingService.cs
- PdfAPI\Services\PdfService.cs
- PdfAPI.Core\Services\PdfClientService.cs
